package com.example.spring.ai.controller;

import com.example.spring.ai.service.CustomerSupportAssistant;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 测试ChatClient调用AI模型
 *
 * @author DuGuanghan
 * @since 2025-03-25 15:57:36
 */
@RestController
@RequestMapping("/ai/chat")
public class ChatClientController {

    private final ChatClient openAiClient;
    private final CustomerSupportAssistant customerSupportAssistant;

    public ChatClientController(ChatClient openAiClient, CustomerSupportAssistant customerSupportAssistant) {
        this.openAiClient = openAiClient;
        this.customerSupportAssistant = customerSupportAssistant;
    }

    record ActorFilms(String actor, List<String> movies) {}

    /**
     * 阻塞式对话
     *
     * @param message 用户消息
     * @return {@link String }
     * @author DuGuanghan
     * @since 2025-03-25 15:58:23
     */
    @RequestMapping("/generate")
    public String openAiChatGenerate(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
        return openAiClient.prompt().user(message).call().content();
    }

    /**
     * 格式化输出结果
     *
     * @param message 消息
     * @return {@link ActorFilms }
     * @author DuGuanghan
     * @since 2025-03-25 15:59:11
     */
    @RequestMapping("/actor")
    public ActorFilms openAiChatActor(@RequestParam(value = "message", defaultValue = "生成成龙的5部电影") String message) {
        return openAiClient.prompt().user(message).call().entity(ActorFilms.class);
    }

    /**
     * 格式化输出结果（转为集合形式）
     * @param message 消息
     * @return {@link List }<{@link ActorFilms }>
     * @author DuGuanghan
     * @since 2025-03-25 15:59:47
     */
    @RequestMapping("/actors")
    public List<ActorFilms> openAiChatActors(@RequestParam(value = "message", defaultValue = "生成成龙的5部电影") String message) {
        return openAiClient.prompt().user(message).call().entity(new ParameterizedTypeReference<List<ActorFilms>>() {
        });
    }

    /**
     * 格式化输出结果（使用BeanOutputConverter转为集合形式）
     * @return {@link List }<{@link ActorFilms }>
     * @author DuGuanghan
     * @since 2025-03-25 16:00:28
     */
    @RequestMapping("/randomActor")
    public List<ActorFilms> openAiChatRandomActor() {
        var converter = new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorFilms>>() {});

        Flux<String> flux = this.openAiClient.prompt()
                .user(u -> u.text("""
                        Generate the filmography for a random actor.
                        {format}
                      """)
                        .param("format", converter.getFormat()))
                .stream()
                .content();

        String content = flux.collectList().block().stream().collect(Collectors.joining());

        return converter.convert(content);
    }

    /**
     * 带系统提示的聊天
     *
     * @param message 消息
     * @param voice   语气
     * @return {@link String }
     * @author DuGuanghan
     * @since 2025-03-25 16:01:59
     */
    @RequestMapping("/chatWithSystemText")
    public String openAiChatWithSystemText(@RequestParam(value = "message", defaultValue = "讲个笑话") String message,
                                           @RequestParam(value = "voice") String voice) {
        return openAiClient.prompt()
                .system(s -> s.param("voice", voice))
                .user(message)
                .call()
                .content();
    }

    /**
     * 聊天时携带上下文消息
     *
     * @param chatId  会话ID
     * @param message 消息
     * @return {@link Flux }<{@link String }>
     * @author DuGuanghan
     * @since 2025-03-25 16:02:49
     */
    @RequestMapping("/customer")
    public Flux<String> openAiCustomer(@RequestParam(value = "chatId", defaultValue = "1") String chatId, @RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
        return customerSupportAssistant.chat(chatId, message);
    }

}
